package com.os.opencv.java.chapter11;

import org.opencv.core.*;
import org.opencv.features2d.DescriptorMatcher;
import org.opencv.features2d.Features2d;
import org.opencv.features2d.SIFT;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;

import java.util.ArrayList;
import java.util.List;

public class FLANN {

    public static void main(String[] args) {
        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
        //读取图像并在屏幕上显示
        Mat img1 = Imgcodecs.imread("pics/face.jpg", Imgcodecs.IMREAD_GRAYSCALE);
        HighGui.imshow("face1", img1);
        Mat img2 = img1.clone();

        //用sift算法检测图像中的关键点
        SIFT detector = SIFT.create();
        MatOfKeyPoint kp1 = new MatOfKeyPoint();
        MatOfKeyPoint kp2 = new MatOfKeyPoint();
        Mat descriptor1 = new Mat();
        Mat descriptor2 = new Mat();
        detector.detectAndCompute(img1, new Mat(), kp1, descriptor1);
        detector.detectAndCompute(img2, new Mat(), kp2, descriptor2);

        //创建descriptormatcher对象并进行knn匹配
        DescriptorMatcher matcher = DescriptorMatcher.create(DescriptorMatcher.FLANNBASED);
        List<MatOfDMatch> knnMatches = new ArrayList<>();
        matcher.knnMatch(descriptor1, descriptor2, knnMatches, 2);

        //用low比率测试筛选匹配项
        float ratioThresh = 0.75f;
        List<DMatch> goodOnes = new ArrayList<>();
        for(int i=0; i<knnMatches.size(); i++){
            if(knnMatches.get(i).rows() > 1){
                DMatch[] matches = knnMatches.get(i).toArray();
                if(matches[0].distance < ratioThresh * matches[1].distance){
                    goodOnes.add(matches[0]);
                }
            }
        }
        MatOfDMatch goodMatches = new MatOfDMatch();
        goodMatches.fromList(goodOnes);

        //绘制匹配项
        Mat dst = new Mat();
        Features2d.drawMatches(img1, kp1, img2, kp2, goodMatches, dst, Scalar.all(-1), Scalar.all(-1), new MatOfByte());

        //在屏幕上绘制有匹配角点连接线的图像
        HighGui.imshow("matches", dst);
        HighGui.waitKey(0);

        System.exit(0);

    }
}
